// CirQueue.hpp
// Author: Paddy Huang
// Date: 2020.03.11 17:37

// Circle Queue
#ifndef CIR_QUEUE_HXX 
#define CIR_QUEUE_HXX

#include <iostream>
using namespace std;

template<class T, int size = 10>
class CirQueue{
    public:
        CirQueue();
        ~CirQueue();

        void Enqueue(T value);
        T Dequeue();

		const T GetQueue();   // Get top element, but no delete
        const bool isEmpty() noexcept ;

    private:
		int front; 
        int rear;
		T elements[size];
};

template<class T, int size>
CirQueue<T, size>::CirQueue(){
	front = 0;
	rear = 0;
}

template<class T, int size>
CirQueue<T, size>::~CirQueue(){
	cout << "Destroy queue" << endl;
}

template<class T, int size>
void CirQueue<T, size>::Enqueue(T value){
	if((rear + 1) % size == front){		// Judge queue is empty
		cout << "Queue is full" << endl;
		return;
	}
	rear = (rear + 1) % size;	// rear pointer points to the next element
	elements[rear] = value;
}

template<class T, int size>
T CirQueue<T, size>::Dequeue(){
	if(isEmpty()){
		cout << "Queue is empty" << endl;
		exit(EXIT_FAILURE);
	}
	front = (front + 1) % size;	// front pointer points to the next element, which means deletes element
	return elements[front];
}

template<class T, int size>
const T CirQueue<T, size>::GetQueue() noexcept {
	if(isEmpty()){
		cout << "Queue is empty" << endl;
		return;
	}
	return elements[(front + 1) % size];
}

template<class T, int size>
const bool CirQueue<T, size>::isEmpty() noexcept {
	return front == rear;
}

#endif
